package com.wan37.logic.listener.handler;

import com.wan37.logic.db.AsynDBManager;
import com.wan37.logic.domain.entity.UserSkillDO;
import com.wan37.logic.domain.vo.SkillVO;
import com.wan37.logic.global.reference.SpringContextHolder;
import com.wan37.logic.listener.annotation.EventHandler;
import com.wan37.logic.listener.annotation.Listener;
import com.wan37.logic.listener.event.EventType;
import com.wan37.logic.listener.event.role.RoleCreateEvent;
import com.wan37.logic.listener.event.user.UserLoginEvent;
import com.wan37.logic.service.UserSkillService;
import com.wan37.logic.service.cache.RoleServiceCache;
import com.wan37.logic.service.cache.SkillServiceCache;
import com.wan37.logic.service.cache.UserServiceCache;
import com.wan37.logic.utils.SkillLevelUtil;
import com.wan37.protobuf.constant.SkillLabel;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 技能相关监听器
 *
 * @author : luoyong
 * @date : 2020-06-29 11:06
 **/
@Listener
public class SkillListenerHandler {

    private UserSkillService userSkillService;
    private SkillServiceCache skillServiceCache;
    private RoleServiceCache roleServiceCache;
    private UserServiceCache userServiceCache;
    private SkillLevelUtil skillLevelUtil;
    private AsynDBManager asynDBManager;

    public SkillListenerHandler() {
        this.userSkillService = SpringContextHolder.getBean("userSkillService");
        this.skillServiceCache = SpringContextHolder.getBean("skillServiceCache");
        this.roleServiceCache = SpringContextHolder.getBean("roleServiceCache");
        this.skillLevelUtil = SpringContextHolder.getBean("skillLevelUtil");
        this.userServiceCache = SpringContextHolder.getBean("userServiceCache");
        this.asynDBManager = SpringContextHolder.getBean("asynDBManager");
    }

    @EventHandler(value = EventType.LOGIN)
    public void Login(UserLoginEvent userLoginEvent) {
        String userId = userLoginEvent.getUserId();
        userServiceCache.getUserServiceMap().get(userId).getRoleIdList();
        List<UserSkillDO> userSkillDOList = userSkillService.getUserSkillDOsByUserId(userId);
        SkillVO newSkillVO = null;
        for (UserSkillDO userSkillDO : userSkillDOList) {
            SkillVO skillVO = skillServiceCache.getSkillServiceMap().
                    get(userSkillDO.getSkillId()).getSkillVO();
            newSkillVO = new SkillVO(skillVO);
            int level = userSkillDO.getLevel();
            float enhance = skillLevelUtil.skillLevelMap.get(Integer.toString(level));
            Map<String, Long> numberMap = new ConcurrentHashMap<>();
            skillVO.getNumberMap().forEach((key, value) -> numberMap.put(key, (long) (value * enhance)));
            newSkillVO.setLevel(level);
            newSkillVO.setUsage(userSkillDO.getUsage());
            newSkillVO.setNumberMap(numberMap);
            if (roleServiceCache.getRoleServiceMap().get(userSkillDO.getUsage()).getSkillVOMap() == null) {
                Map<String, SkillVO> skillVOMap = new HashMap<>();
                skillVOMap.put(userSkillDO.getSkillId(), newSkillVO);
                roleServiceCache.getRoleServiceMap().get(userSkillDO.getUsage()).setSkillVOMap(skillVOMap);
            } else {
                roleServiceCache.getRoleServiceMap().get(userSkillDO.getUsage())
                        .getSkillVOMap().put(userSkillDO.getSkillId(), newSkillVO);
            }
        }
    }

    @EventHandler(EventType.ROLE_CREATE)
    public void roleCreate(RoleCreateEvent roleCreateEvent) {
        RoleServiceCache.Role role = roleServiceCache.getRoleServiceMap().get(roleCreateEvent.getRoleId());
        Map<String, SkillVO> skillVOMap = new HashMap<>();
        for (SkillServiceCache.Skill skill : skillServiceCache.getSkillServiceMap().values()) {
            if (skill.getSkillVO().getProfession().equals(role.getRoleVO().getProfession())
                    || skill.getSkillVO().getProfession().equals(SkillLabel.ORDINARY)) {
                SkillVO skillVO = new SkillVO(skill.getSkillVO());
                skillVO.setLevel(1);
                skillVO.setUsage(role.getRoleVO().getAllRoleId());
                skillVOMap.put(skillVO.getId(), skillVO);
                UserSkillDO userSkillDO = new UserSkillDO();
                userSkillDO.setUsage(roleCreateEvent.getRoleId());
                userSkillDO.setUserId(roleCreateEvent.getUserId());
                userSkillDO.setLevel(skillVO.getLevel());
                userSkillDO.setSkillId(skillVO.getId());
                asynDBManager.distributeWork(roleCreateEvent.getUserId(), () -> userSkillService.save(userSkillDO));
            }
        }
        role.setSkillVOMap(skillVOMap);
    }
}
